Fix #18: emit parse_path in function-call form for lambda params#21
Open
piotrszul wants to merge 1 commit into
Open
Fix #18: emit parse_path in function-call form for lambda params#21piotrszul wants to merge 1 commit into
piotrszul wants to merge 1 commit into
Conversation
92da49a to
c078d18
Compare
The struct backend generated DuckDB SQL that failed to bind on DuckDB
1.4.x for any forEach/forEachOrNull select containing a getReferenceKey()
column, e.g.:
Binder Error: Referenced column "el" not found in FROM clause!
getReferenceKey() expands to a where() predicate whose _splitPath step
compiles to `el.parse_path('/')[...]` — a method call with the lambda
parameter as the receiver. When that predicate sits in a list_filter
nested inside the forEach's list_transform, DuckDB 1.4.x's binder fails
to resolve the lambda parameter. It is not a name-shadowing problem
(renaming the inner parameter does not help, and reusing the same name
with the function-call form works fine); the trigger is specifically a
lambda parameter used as a *method-call receiver* inside a nested
list_filter predicate.
Emitting the equivalent function-call form `parse_path(el, '/')[...]`
binds correctly on both 1.4.x and 1.5.x. The non-lambda _splitPath case
stays method-chained so flattenSql can join it onto the preceding
navigation segment.
Verification:
- New e2e test reproduces the issue's minimal case (forEachOrNull
participant + getReferenceKey(Practitioner)) and runs the generated
SQL against the bundled DuckDB 1.4.1 — RED before, GREEN after.
- Full suite: 192 pass / 0 fail (was 191; +1 new test).
- End-to-end: built the issue's MinimalRepro.json via the CLI and ran
the generated SQL on DuckDB 1.4.1 -> id,practitioner_id / enc1,prac1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
c078d18 to
7865271
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The default (struct) backend generated DuckDB SQL that fails to bind on DuckDB 1.4.x for any
forEach/forEachOrNullselect containing agetReferenceKey()column (e.g.EncounterFlat'sparticipant/location):The same SQL ran fine on DuckDB 1.5.x. Reported in #18.
Root cause
getReferenceKey(Type)expands toreference.where(_splitPath(-2) = 'Type')._splitPath(-1). The_splitPathstep inside thewhere()predicate compiled toel.parse_path('/')[...]— a method call with the lambda parameter as the receiver. When that predicate sits in alist_filternested inside theforEach'slist_transform, DuckDB 1.4.x's binder fails to resolve the lambda parameter.The issue originally hypothesised parameter shadowing (inner
elshadowing outerel). Investigation against DuckDB 1.4.1 showed that is not the cause:el_1) does not fix it.eltogether with the function-call form works fine.el.parse_path(...)) inside alist_filterpredicate nested in another lambda. Nestedlist_transformwith the same construct binds fine; plain (non-receiver) uses of the parameter bind fine.Fix
Emit the equivalent function-call form
parse_path(el, '/')[...]instead of the method-call formel.parse_path('/')[...]when_splitPathoperates on a lambda parameter. This binds correctly on both 1.4.x and 1.5.x. The non-lambda_splitPathcase stays method-chained soflattenSqlcan still join it onto the preceding navigation segment.One-case, general change in
src/ddb-sql-builder.js.Verification
tests/e2e.test.js) reproduces the issue's minimal case (forEachOrNull: participant+individual.getReferenceKey(Practitioner)) and executes the generated SQL against the bundled DuckDB 1.4.1 — RED before the fix (Binder Error), GREEN after.MinimalRepro.jsonvia the CLI and ran the generated.sqlon DuckDB 1.4.1 →id,practitioner_id/enc1,prac1.Notes / out of scope
origin/master; no other fixes folded in.🤖 Generated with Claude Code